#include "Bone.h"
#include "dataTypes.h"

Bone::Bone()
{
	parent = NULL;
	angle = 0;
	length = 0;
	lengthMultiplier = 1;
	x = 0;
	y = 0;
	width = 0;

	keyFrame = NULL;
	isAnimating = false;
}

Bone::Bone(float aAngle, float aLength, float aWidth, Bone* aParent)
{
	parent = aParent;
	angle = aAngle;
	length = aLength;
	lengthMultiplier = 1;
	x = parent->GetJointX();
	y = parent->GetJointY();

	width = aWidth;
	keyFrame = NULL;
	isAnimating = false;
}

Bone::Bone(const Bone& b)
{
	operator=(b);
}

Bone::~Bone()
{
	for(unsigned int i=0; i<childs.size(); i++) delete childs[i];
}

Bone& Bone::operator=(const Bone& b)
{
	angle = b.angle;
	length = b.length;
	lengthMultiplier = b.lengthMultiplier;
	x = b.x;
	y = b.y;
	width = b.width;
	keyFrame = NULL;
	isAnimating = false;

	for(unsigned int i=0; i<b.childs.size(); i++)
	{
		Bone* child = new Bone();
		*child = *(b.childs[i]);
		childs.push_back(child);
		childs[i]->parent = this;
	}

	parent = NULL;

	return *this;
}

Bone* Bone::GetChild(unsigned int aI)
{
	if(aI < 0 || aI > childs.size()) return NULL;
	return childs[aI];
}

Bone* Bone::AddChild(float aAngle, float aLength, float aWidth)
{
	Bone* child = new Bone(aAngle,aLength,aWidth,this);
	childs.push_back(child);

	return child;
}

float Bone::GetJointX()
{
	return sin(angle)*length*lengthMultiplier + x;
}

float Bone::GetJointY()
{
	return -cos(angle)*length*lengthMultiplier + y;
}

void Bone::SetLength(float aLength)
{
	lengthMultiplier = aLength;

	for(unsigned int i=0; i<childs.size(); i++)
	{
		childs[i]->SetX(GetJointX());
		childs[i]->SetY(GetJointY());
		childs[i]->SetLength(childs[i]->GetLengthMultiplier());
	}
}

void Bone::SetAngle(float aAngle)
{
	angle = aAngle;

	for(unsigned int i=0; i<childs.size(); i++)
	{
		childs[i]->SetX(GetJointX());
		childs[i]->SetY(GetJointY());
		childs[i]->SetAngle(childs[i]->GetAngle());
	}
}

void Bone::Tick()
{
	if(keyFrame != NULL)
	{
		// Save initial bone at start
		if(!isAnimating)
		{
			isAnimating = true;
			animationFrame = 0;
			angleBefore = angle;
			lengthBefore = lengthMultiplier;
		}

		float astep = keyFrame->angle - angleBefore;
		float lstep = keyFrame->length - lengthBefore;

		float angleStep = astep/keyFrame->duration;
		SetAngle(angleBefore + angleStep*animationFrame);

		float lengthStep = lstep/keyFrame->duration;
		SetLength(lengthBefore + lengthStep*animationFrame);

		// Apply frame if time has come
		if(animationFrame++ >= keyFrame->duration)
		{
			angle = keyFrame->angle;
			lengthMultiplier = keyFrame->length;
			isAnimating = false;
			animationFrame = 0;
			keyFrame = keyFrame->nextFrame;
		}
	}

	for(unsigned int i=0; i<childs.size(); i++)
	{
		childs[i]->Tick();
	}
}